/*
 * jxUtils Project (2014)
 * 
 * by Denilson Edinaldo Pinto
 * 
 * LGPL
 * Copyright (C) 2014
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.jxUtils.exception;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.jxUtils.check.ParameterCheck;

/**
 * @author Denilson Edinaldo Pinto
 * @porject jxUtils
 * @package org.jxUtils.exception
 * @date 08/02/2014 - 08:49:25
 */
public class MyException extends RuntimeException {
	
	private static final long serialVersionUID = -8957413119093883539L;
	
	private List<Throwable> causes = new ArrayList<Throwable>();
	
	private List<String> details = new ArrayList<String>();
	
	/**
	 * 
	 */
	public MyException() {
	
		super();
	}
	
	/**
	 * @param causes
	 * @param message
	 */
	public MyException(final List<Throwable> causes, final String message) {
	
		super(message);
		
		this.causes = causes;
	}
	
	/**
	 * @param message
	 */
	public MyException(final String message) {
	
		super(message);
	}
	
	/**
	 * @param message
	 * @param details
	 */
	public MyException(final String message, final List<String> details) {
	
		super(message);
		
		this.details = details;
	}
	
	/**
	 * @param message
	 * @param causes
	 * @param details
	 */
	public MyException(final String message, final List<Throwable> causes, final List<String> details) {
	
		super(message);
		
		this.causes = causes;
		this.details = details;
	}
	
	/**
	 * @param message
	 * @param cause
	 */
	public MyException(final String message, final Throwable cause) {
	
		super(message, cause);
		
		addCause(cause);
	}
	
	/**
	 * @param message
	 * @param cause
	 * @param details
	 */
	public MyException(final String message, final Throwable cause, final List<String> details) {
	
		super(message, cause);
		
		addCause(cause);
		
		this.details = details;
	}
	
	/**
	 * @param cause
	 */
	public MyException(final Throwable cause) {
	
		super(cause);
		
		addCause(cause);
	}
	
	/**
	 * @param cause
	 */
	public void addCause(final Throwable cause) {
	
		causes.add(cause);
	}
	
	/**
	 * @param detail
	 */
	public void addDetail(final String detail) {
	
		details.add(detail);
	}
	
	/**
	 * @return the causes
	 */
	public List<Throwable> getCauses() {
	
		return causes;
	}
	
	/**
	 * @return the details
	 */
	public List<String> getDetails() {
	
		return details;
	}
	
	/**
	 * @param causes
	 *        the causes to set
	 */
	public void setCauses(final List<Throwable> causes) {
	
		this.causes = causes;
	}
	
	/**
	 * @param details
	 *        the details to set
	 */
	public void setDetails(final List<String> details) {
	
		this.details = details;
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Throwable#toString()
	 */
	@Override
	public String toString() {
	
		return toString(this);
	}
	
	/**
	 * @param exception
	 * @param file
	 * @throws FileNotFoundException
	 */
	public static final void toFile(final Throwable exception, final File file) throws FileNotFoundException {
	
		ParameterCheck.isNull(exception, "exception");
		ParameterCheck.isNull(file, "file");
		
		exception.printStackTrace(new PrintStream(file));
	}
	
	/**
	 * @param exception
	 * @param absolutePathFile
	 * @throws FileNotFoundException
	 */
	public static final void toFile(final Throwable exception, final String absolutePathFile) throws FileNotFoundException {
	
		ParameterCheck.isNull(exception, "exception");
		ParameterCheck.isNullOrAbsoluteEmpty(absolutePathFile, "absolutePathFile");
		
		toFile(exception, new File(absolutePathFile));
	}
	
	/**
	 * @param exceptions
	 * @param files
	 * @throws FileNotFoundException
	 * @since <br>
	 *        exceptions[0] -> files[0]
	 * @since exceptions[1] -> files[1]
	 * @since exceptions[2] -> files[2]
	 * @since ... <br>
	 */
	public static final void toFiles(final List<Throwable> exceptions, final List<File> files) throws FileNotFoundException {
	
		ParameterCheck.isNullOrEmpty(exceptions, "exceptions");
		ParameterCheck.isNullOrEmpty(files, "files");
		
		int index = 0;
		
		//
		for(final File file : files) {
			
			toFile(exceptions.get(index), file);
			
			index++;
		}
	}
	
	/**
	 * @param exceptions
	 * @return formated exceptions message
	 */
	public static final String toString(final Collection<Throwable> exceptions) {
	
		ParameterCheck.isNullOrEmpty(exceptions, "exceptions");
		
		final StringBuilder mesage = new StringBuilder();
		
		//
		for(final Throwable exception : exceptions) {
			
			mesage.append(toString(exception) + "\n\n");
		}
		
		return mesage.toString();
	}
	
	/**
	 * @param exception
	 * @return formated exception message
	 */
	public static final String toString(final Throwable exception) {
	
		ParameterCheck.isNull(exception, "exception");
		
		final StringWriter stringWriter = new StringWriter();
		
		exception.printStackTrace(new PrintWriter(stringWriter));
		
		return stringWriter.toString();
	}
}
